Skip to content

Conversation

@anara123
Copy link

@anara123 anara123 commented Feb 9, 2026

Some OAuth providers (e.g. HubSpot) require client credentials to be sent as POST body parameters (client_secret_post) instead of via HTTP Basic Auth header. The oauth2 crate defaults to BasicAuth, and rmcp had no way to honor the server's advertised auth method, causing TokenExchangeFailed errors.

Derive token_endpoint_auth_method from the server's authorization metadata (token_endpoint_auth_methods_supported) during configure_client. When the server advertises client_secret_post, the client is set to AuthType::RequestBody; otherwise it defaults to
BasicAuth. No new config fields are added — the behavior is driven entirely by server metadata.

Motivation and Context

OAuth servers advertise supported token endpoint auth methods via token_endpoint_auth_methods_supported in their authorization server metadata. rmcp was ignoring this field, always using Basic Auth. Servers like HubSpot that require client_secret_post would reject token requests.

How Has This Been Tested?

Tested with a simple MCP client connecting to HubSpot's remote MCP server (https://mcp.hubspot.com/mcp), which requires client_secret_post authentication.

Breaking Changes

No breaking changes.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

The TypeScript MCP SDK already implements the same token_endpoint_auth_methods_supported pattern:

  • packages/core/src/shared/auth.ts — defines token_endpoint_auth_methods_supported in OAuthMetadataSchema
  • packages/client/src/client/auth.tsselectClientAuthMethod() reads token_endpoint_auth_methods_supported from server metadata and picks between client_secret_basic, client_secret_post, or none; applyClientAuthentication() then sends credentials accordingly (Basic header vs POST body)

This PR aligns the Rust SDK with the TypeScript SDK's existing behavior.

Some OAuth providers (e.g. HubSpot) require client credentials to be
sent as POST body parameters (client_secret_post) instead of via HTTP
Basic Auth header. The oauth2 crate defaults to BasicAuth, and rmcp
had no way to override this, causing TokenExchangeFailed errors.

Add an optional `token_endpoint_auth_method` field to OAuthClientConfig
that accepts "client_secret_post" (RequestBody) and "client_secret_basic"
(BasicAuth). Unknown values are silently ignored, preserving the default.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions bot added T-core Core library changes T-examples Example code changes T-transport Transport layer changes labels Feb 9, 2026
Move auth method selection from per-client config to server's
AuthorizationMetadata, which is the correct OAuth 2.0 approach.
Servers like HubSpot advertise token_endpoint_auth_methods_supported
in their metadata; reading it from there avoids manual configuration
and prevents TokenExchangeFailed errors with non-BasicAuth providers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions bot removed the T-examples Example code changes label Feb 9, 2026
Anar Azadaliyev and others added 2 commits February 9, 2026 19:22
…ional_fields

Move token_endpoint_auth_methods_supported out of AuthorizationMetadata
as an explicit field and read it from the serde(flatten) additional_fields
HashMap instead. This avoids serializing `null` when the field is absent,
which broke Zod validation in downstream consumers like MCP Inspector.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… test assertions

When token_endpoint_auth_methods_supported contains both client_secret_post
and client_secret_basic, default to basic auth per RFC 6749 §2.3.1.
Update configure_client tests to assert actual AuthType instead of is_some().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@anara123
Copy link
Author

@alexhancock Hi Alex, any chance you can take a look at the PR

@alexhancock
Copy link
Contributor

@anara123 Thanks for noticing this and providing a solution.

@wdawson Has a comprehensive PR to make auth compliant with the 11-25-2025 rev of the MCP spec here #651

Should we merge both, or include something smaller in #651 to address the concern?

@wdawson
Copy link

wdawson commented Feb 12, 2026

@anara123 Thanks for noticing this and providing a solution.

@wdawson Has a comprehensive PR to make auth compliant with the 11-25-2025 rev of the MCP spec here #651

Should we merge both, or include something smaller in #651 to address the concern?

Definitely both! This was a good find!

@alexhancock
Copy link
Contributor

@anara123 Do you mind running cargo fmt and re-push?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-core Core library changes T-transport Transport layer changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants